import { Graph, View } from '@antv/x6';
import { createApp, defineComponent, onMounted, onUnmounted, PropType, ref,reactive, watch } from 'vue';
import { getIndexCells, addChildNode,findItem, removeNode, replaceNode, mapAllNode,clearOtherField } from './indexData';
import { TeleportContainer } from './registerIndexNode';
import EdgeLabel from './edgeLabel';
import {nanoid} from  'nanoid'
import Bus from '@/utils/emmit'
import {debounce, cloneDeep} from 'lodash'
import API from '@/services';
import { useRouter, useRoute} from 'vue-router';
import { Message } from '@arco-design/web-vue';
import * as RouteNames from '@/router/consts';
import {defaultConfig} from '@/constants/indexTree'
export default defineComponent({
    name: 'IndexGraph',
    props: {
        treedata: Object as PropType<any>
    },
    // inject: ["getGraph", "getNode"],
    
    setup: (props, {emit}) => {
        const domRef = ref();
         // todo: 是否需要 ref
        const graphContext = ref();
        const getParentId = ref()
        const router = useRouter();
        const route = useRoute();
        const id = route.query.id
        
        const metricsConfigObj = reactive({
            value: {
                ...defaultConfig
            }
        })
        const initGraph = () => {
            if (domRef.value) {
                graphContext.value = new Graph({
                container: domRef.value,
                autoResize: document.body,
                connecting: {
                    connectionPoint: 'anchor',
                },
                grid: {
                    size: 10,
                    visible: true,
                    type: 'dot', // 'dot' | 'fixedDot' | 'mesh'
                    args: {
                    color: '#D4D7E1', // 网格线/点颜色
                    thickness: 1, // 网格线宽度/网格点大小
                    },
                },
                interacting: {
                    nodeMovable: false,
                },
                panning: {
                    enabled: true,
                    eventTypes: ['leftMouseDown', 'mouseWheel'],
                },
                mousewheel: {
                    enabled: true,
                    modifiers: 'ctrl',
                    factor: 1.1,
                    maxScale: 1.5,
                    minScale: 0.5,
                },
                onEdgeLabelRendered: (args:any) => {
                    const { selectors, edge: { data: { source,target } } } = args
                    const content = selectors.foContent as HTMLDivElement
                    if (content) {
                        // @ts-ignore
                      const app = createApp(<EdgeLabel data={source} onChangeSymbolEdge={
                        onChangeSymbolEdge
                      } />);
                      app.mount(content)
                    }
                },
                })
                graphContext.value.on('node:click', ({ node }: any) => {
                    getParentId.value = node?.id
                })
                graphContext.value.on('node:mouseenter', ({ node }: any) => {
                    const curType = node.store.data.data.type
                    console.log('curType', curType)
                    if (curType === "symbolCard") {
                        getParentId.value = node?.id
                    }
                })
            }
        }
        // 点击删除时固定住画布不能拖动
        const onPopoverDelete = (v:any) => {
            if (v) {
                graphContext.value.disablePanning()
            } else {
                graphContext.value.enablePanning()
            }
        }
        Bus.on('onRestEvent', () => {
            graphContext.value.centerContent()
        })
        const onChangeSymbolEdge = (v:any, b:boolean) => {
            let findSymbolCorrelation = findItem(props.treedata, v.id)
            
            const correlation = {
                correlation: b
            }
            findSymbolCorrelation = Object.assign(findSymbolCorrelation?.node, correlation)
        }

        // 删除指标
        const onRemoveEvent = (data: any) => {
            const removeData = removeNode(props.treedata, data.id)
            if (removeData) {
                const models = getIndexCells(props.treedata, onRemoveEvent, onAddIndexCard, clickMetricsCard, onPopoverDelete);
                graphContext.value.fromJSON(models)
            } else {
                graphContext.value.dispose()
            }
            emit('removeEvent', data,props.treedata, props.treedata.id === data.id)
        }
        // 点击选中指标重构脑图
        const clickMetricsCard = (data:any) =>{
            const findNode = mapAllNode(props.treedata, data.id)
            if (findNode) {
                data.heightLightLine = true
                const models = getIndexCells(props.treedata, onRemoveEvent, onAddIndexCard, clickMetricsCard,onPopoverDelete);
                graphContext.value.fromJSON(models)
            }
        }

        // 添加指标节点
        const addMetricsNode = (cloneData:any) => {
            cloneData.heightLightLine = true
            const metricsNode = addChildNode(props.treedata, cloneData, getParentId.value, 'addMetricsNode')
            if (metricsNode) {
                const models = getIndexCells(props.treedata, onRemoveEvent, onAddIndexCard, clickMetricsCard,onPopoverDelete);
                graphContext.value.fromJSON(models)
            }
        }
        // 替换指标卡节点
        const replaceMertricsNode = (data:any, currentIndex:any) => {
            const changeIndex = replaceNode(props.treedata, data, currentIndex.id)

            if (changeIndex) {
                const models = getIndexCells(props.treedata, onRemoveEvent, onAddIndexCard, clickMetricsCard,onPopoverDelete);
                graphContext.value.fromJSON(models)
            }
        }

        // 预览指标
        Bus.on('previewMetricsCard', (v:any) => {
            let findIndexCard = findItem(props.treedata, v.id)
            v.heightLightLine = true
            // 替换结果
            if (findIndexCard) {
                findIndexCard = Object.assign(findIndexCard.node, v)
            }
            const models = getIndexCells(props.treedata, onRemoveEvent, onAddIndexCard, clickMetricsCard,onPopoverDelete);
            graphContext.value.fromJSON(models)
            
        })

        const previewApi = async (card: any) => {
            try {
                const res = await API.metricsTree.postCardPreview(card);
                return res
            } catch (error) {throw error;}
        };
        // 统计周期跟默认数据时间粒度保持一致
        const getFilterDimension = async (id: any) => {
            try {
                const { code, data } =
                    await API.metricsModelRelation.getGetMetricsFilterById({
                        id
                    });
                    if (code === 200) {
                        return data
                    }
            } catch (error) {}
        };
        const getPreviewParams = async (v:any) => {
            const res = await getFilterDimension(v.metricsId);
            v.keys = v.id
            const {id, metricsName, metricsId, cardName, keys} = v 
            const val = {
                id,
                metricsName,
                metricsId,
                cardName,
                keys
            }
            const mergeData = cloneDeep({...metricsConfigObj.value, ...val})
            if (res?.ifGroupBy) {
                mergeData.dateCondition.timeUnit = res?.timeframe?.toLocaleUpperCase()
            } else {
                mergeData.dateCondition.timeUnit = metricsConfigObj.value.metricsSetting.statisticalPeriod.timeUnit
            }
            mergeData.cardName = mergeData.metricsName
            delete mergeData.compare

            return mergeData
        }
        // 在画布中添加指标卡时
        /**
         * 
         * @param v 指标节点
         * @param type 指标操作类型，addNode:添加指标；replaceNode:切换指标
         */
        const addGraphMetricsCard = async (v:any, type:string, sourceNode?:any)=>{
            const previewParams = await getPreviewParams(v)
            delete previewParams.dateTime
            previewApi(previewParams).then((res:any)=>{
                if (res.code === 200) {
                    delete res.data?.sqlFormat
                    const newNodePramas = Object.assign(metricsConfigObj.value, res.data)
                    const getPreviewData = {
                        ...newNodePramas,
                        compare: res.data?.compare || metricsConfigObj.value.compare,
                        id: res.data.keys
                    }
                    const otherParams = {
                        type: 'indexCard',
                        children: [],
                        heightLightLine: true, // 默认选中时高亮
                    }
                    const mergeData = cloneDeep(getPreviewData) // 将数据带出去作为保存时入参cards一部分
                    const cloneData = cloneDeep({...getPreviewData, ...otherParams}) // 传到脑图树graph中
                    if (type === 'addNode') {
                        Bus.emit('addMetricsCard', mergeData) 
                        addMetricsNode(cloneData)
                    }
                    if (type === 'replaceNode') {

                        Bus.emit('replaceSuccessMertrics', mergeData, sourceNode)
                        replaceMertricsNode(cloneData, sourceNode)
                        Message.success('指标卡切换成功')
                    }
                    
                } else {
                    Message.error(res.msg)
                    return;
                }
            })
        }
        /**
         * 
         * @param data 
         * @param o o:{symbolType: true/false,cardType:'metrics'/'symbol' }
         * symbolType:true 切换关系；symbolType:false 添加关系
         * cardType:'metrics' 操作的是指标；
         * cardType:'symbol' 操作的是符号；
         */
        const onAddIndexCard = async (data: any, obj:any) => {
            //tode:处理新增节点情况
            const cloneData = cloneDeep(data)
            cloneData.id = nanoid(10)
            if (data.type === 'indexCard') {
                addGraphMetricsCard(cloneData, 'addNode')
                return
            }
            // todo:这是符号切换
            let resultNode
            if (obj.symbolType && obj.cardType === 'symbol') {
                resultNode = replaceNode(props.treedata, cloneData, getParentId.value)
            } else {
                resultNode = addChildNode(props.treedata, cloneData, getParentId.value, 'addSymbolNode')
            }
            if (resultNode) {
                const models = getIndexCells(props.treedata, onRemoveEvent, onAddIndexCard, clickMetricsCard,onPopoverDelete,data);
                graphContext.value.fromJSON(models)
            }
        }

        // 切换指标卡时首先判断下预览情况
        Bus.on('exchangeMetricsCard', (targetNode:any, sourceNode:any) => {
            addGraphMetricsCard(targetNode, 'replaceNode', sourceNode)
        })

        // 指标保存时
        /**
         * @treeName 指标树名称
         * @description 指标树描述
         * @treeId 指标树编辑状态id
         */
        Bus.on('metricsCardSave', (cards:any, treeName:any, description:string, treeId:any) => {
            const saveGraphPrams = cloneDeep(clearOtherField(props.treedata))
            const graphStr = JSON.stringify(saveGraphPrams)
            const saveParams = cards.map((item:any)=>{
                if (!item?.compare?.compareName) {
                    delete item.compare
                    return {
                        ...item
                    }
                }
                return {
                    ...item
                }
            })
            let params :any = {
                cards: saveParams,
                treeName,
                description,
                graph: graphStr,
                id: treeId
            }
            if (!id || id === 'undefined') {
                delete params.id
            }
            saveIndex(params)
        })

        const saveIndex = debounce(async (params:any)=> {
            try {
                const {code, data} = await API.metricsTree.postSave({
                    ...params
                })
                if (code === 200) {
                    Message.success('保存成功')
                    router.push({
                        name: RouteNames.ROUTER_INDEXTREE
                    })
                }
            } catch (error) {
            }
        }, 3000, {
            'leading': true,
            'trailing': false
        })
        onMounted( async ()=>{
            await initGraph()
        })
        watch(
            () => props.treedata,
            (val) => {
                /**** 删除主指标后从新进来时需要事先初始化一遍画布dom*****/
                if (!props.treedata.children?.length) {
                    initGraph()
                }
                if (val) {
                    const models = getIndexCells(val, onRemoveEvent, onAddIndexCard, clickMetricsCard,onPopoverDelete);
                    if (graphContext.value) {
                        graphContext.value.fromJSON(models)
                        setTimeout(() => {
                            graphContext.value.positionPoint({ x: models?.nodes?.[0]?.x, y: models?.nodes?.[0]?.y }, 10, '42%')
                        }, 100)
                    }
                }
            }
        )
        onUnmounted(() => {
            graphContext.value.dispose()
        })
        return () => {
            return (
                <>
                    <TeleportContainer />
                    <div ref={domRef}  style={{ width: '100%', height: '100%' }}></div>
                </>
            )
        }
    }
})